package com.woshua.writer;

import com.woshua.JsonKnife;
import com.woshua.utils.AnnotationUtil;

import java.io.IOException;
import java.io.Writer;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.processing.Filer;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;

/*
 * 抽象的辅助类生成器
 * */
public abstract class AbstractWriter implements AdapterWriter {

    private final Filer filer;
    protected ProcessingEnvironment processingEnvironmentEnt;

    public AbstractWriter(ProcessingEnvironment processingEnvironment) {
        this.processingEnvironmentEnt = processingEnvironment;
        filer = this.processingEnvironmentEnt.getFiler();
    }

    @Override
    public void generate(Map<String, List<VariableElement>> map) {
        //模板方法  确定算法的框架,算法具体实现可以归结到子类中
        Iterator<Map.Entry<String, List<VariableElement>>> iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, List<VariableElement>> entry = iterator.next();
            List<VariableElement> cacheElements = entry.getValue();
            if (cacheElements == null) {
                continue;
            }

            InjectorInfo info = createInjectorInfo(cacheElements.get(0));
            Writer writer = null;
            JavaFileObject javaFileObject;
            try {
                processingEnvironmentEnt.getMessager().printMessage(Diagnostic.Kind.NOTE, info.getClassFullPath());
                javaFileObject = this.filer.createSourceFile(info.getClassFullPath());

                writer = javaFileObject.openWriter();
                // 写入package, import, class以及findViews函数等代码段
                generateImport(writer, info);
                // 写入该类中的所有字段到findViews方法中
                for (VariableElement variableElement : entry.getValue()) {
                    writeField(writer, variableElement, info);
                }
                // 写入findViews函数的大括号以及类的大括号
                writeEnd(writer);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (writer != null) {
                        writer.flush();
                    }
                    if (writer != null) {
                        writer.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }
    }

    /**
     * @param element
     * @return
     */
    private InjectorInfo createInjectorInfo(VariableElement element) {
//        属性所属的类
        TypeElement typeElement = (TypeElement) element.getEnclosingElement();
        String packageName = AnnotationUtil.getPackageName(processingEnvironmentEnt, typeElement);
        String className = typeElement.getSimpleName().toString();
        return new InjectorInfo(packageName, className);
    }

    /*
     * 导入包
     * */
    protected abstract void generateImport(Writer writer, InjectorInfo injectInfo) throws IOException;

    /*
     * 生成属性部分
     * */
    protected abstract void writeField(Writer writer, VariableElement variableElement, InjectorInfo injectInfo) throws IOException;

    /*
     * 产生结尾部分
     * */
    protected abstract void writeEnd(Writer writer) throws IOException;

    /*
     * 注入信息
     * */
    class InjectorInfo {
        public String packageName;
        public String className;
        public String newClassName;

        public InjectorInfo(String packageName, String className) {
            this.packageName = packageName;
            this.className = className;
            this.newClassName = className + JsonKnife.SUFFIX;
        }

        /*
         * 辅助类的完整类名
         * */
        public String getClassFullPath() {
            return this.packageName + "." + this.newClassName;
        }
    }
}
